#include <iostream>

namespace application
{

template<typename T>
Plugin<T>::Plugin() : _library(NULL)
{
}

template<typename T>
Plugin<T>::~Plugin()
{
    delete this->_object;
    if(this->_library)
    {
        #ifdef BOARDHELL_WINDOWS
            FreeLibrary(this->_library);
        #endif

        #ifdef BOARDHELL_LINUX
            dlclose(this->_library);
        #endif
    }
}

template<typename T>
T* Plugin<T>::loadPlugin(const std::string& name_plugin)
{
    #ifdef BOARDHELL_WINDOWS
    this->_library = LoadLibrary(name_plugin.c_str());
    #endif

    #ifdef BOARDHELL_LINUX
    this->_library = dlopen(name_plugin.c_str(), RTLD_LAZY);
    #endif

    if(!this->_library)
    {
        std::cout << "Problem while loading library " << name_plugin << std::endl;
    }

    /// "getFactory" might be changed to get a better entry point('cause too restrictive)
    #ifdef BOARDHELL_WINDOWS
    PtrFunc function = reinterpret_cast<PtrFunc>(GetProcAddress(this->_library, "getFactory"));
    #endif

    #ifdef BOARDHELL_LINUX
    PtrFunc function = reinterpret_cast<PtrFunc>(dlsym(this->_library, "getFactory"));
    #endif

    if(!function)
    {
        std::cout << "Entry function not found" << std::endl;
    }

    this->_object = function();

    return this->_object;
}

}
